<?php

namespace Home\Controller;
use Think\Model;
class ChatController extends HomeController {
    protected $config = array('app_type' => 'personal', 'popup' => 'mobile,bind,init,chat_log', 'read' => 'chat_log');

    function test() {

        import("Home.ORG.Util.Gateway");
        Gateway::$registerAddress = '127.0.0.1:1238';

        $push_data['user_id'] = '1';
        $push_data['data'] = json_encode(array('title' => 'title', 'action' => 'action', 'content' => 'content', 'type' => 'type'), JSON_UNESCAPED_UNICODE);
        $push_data['status'] = 0;
        $push_data['time'] = time();

        M('Push') -> add($push_data);
        $from = 1;
        // 发送给谁
        $to = array(1, 2, 3, 4, 5, 6, 7);
        // 消息格式
        $message_data = array('type' => 'push', 'id' => $to, 'from_id' => $from);
        $chat_message = array('message_type' => 'chatMessage', 'data' => $message_data);

        Gateway::sendToUid($to, json_encode($chat_message));
    }

    function admin() {
        $this -> assign("title", '职员查询');
        $node = model("Dept");
        $menu = array();
        $menu = $node -> field('id,pid,name') -> where("is_del=0") -> order('sort asc') -> select();
        $tree = list_to_tree($menu);
        $list = tree_to_list($tree);
        //dump($list);
        $this -> assign('menu', popup_tree_menu($tree));

        $keyword = request('keyword');

        if (!empty($keyword)) {
            $where['name'] = array('like', "%$keyword%");
            $where['emp_no'] = array('like', "%$keyword%");
            $where['letter'] = array('like', "%$keyword%");
            $where['dept_name'] = array('like', "%$keyword%");
            $where['mobile_tel'] = array('like', "%$keyword%");
            $where['_logic'] = "OR";

            $model = model("UserView");
            $field = 'id,emp_no,name,sex,birthday,dept_id,dept_name,position_id,office_tel,mobile_tel,email,duty,is_del,pic';
            $search = $model -> field($field) -> where($where) -> order('emp_no asc') -> select();
            //dump($search);
            $this -> assign('search', $search);
        }
        $this -> display();
    }

    function read($id) {
        if (!empty($id)) {
            $model = M("Dept");
            $dept = tree_to_list(list_to_tree( M("Dept") -> where('is_del=0') -> select(), $id));
            $dept = rotate($dept);
            $dept = implode(",", $dept['id']) . ",$id";

            $where['is_del'] = array('eq', '0');
            $where['dept_id'] = array('eq', $id);
        }

        //dump($where);
        $model = model("UserView");
        $field = 'id,emp_no,name,sex,birthday,dept_id,dept_name,position_id,position_name,office_tel,mobile_tel,email,duty,is_del,pic';
        $data = $model -> field($field) -> where($where) -> order('emp_no asc') -> select();
        $return['data'] = $data;
        $return['status'] = 1;
        $this -> ajaxReturn($return);
    }

    function user_list($id) {
        $where['from'] = array('eq', $id);
        $user_list = M('Message') -> where($where) -> getField('`to` idd,`to`');

        $model = model("UserView");

        if (!empty($user_list)) {
            $where_user['id'] = array('in', array_values($user_list));
            $field = 'id,emp_no,name,sex,birthday,dept_id,dept_name,position_id,position_name,office_tel,mobile_tel,email,duty,is_del,pic';
            $data = $model -> field($field) -> where($where_user) -> order('emp_no asc') -> select();
        }

        $return['data'] = $data;
        $return['status'] = 1;
        $this -> ajaxReturn($return);
    }

    function mobile() {
        $this -> display();
    }

    function bind() {
        import("Home.ORG.Util.Gateway");
        Gateway::$registerAddress = '127.0.0.1:1238';

        // 放入临时变量方便使用
        $laychat_session = $_SESSION['laychat'];

        // 用户id 用户名 个性签名 头像等信息
        $id = $laychat_session['id'];
        $username = $laychat_session['username'];
        $sign = $laychat_session['sign'];
        $avatar = $laychat_session['avatar'];

        // 获得要绑定的client_id，每个client_id对应一个socket链接
        $client_id = $_POST['client_id'];

        // 将client_id与uid绑定，通过Gateway::sendToUid给这个uid发消息(在send_message.php中有调用)
        Gateway::bindUid($client_id, $id);
        // 给client_id设置Gateway的session，方便通过Gateway::getClientSessionsByGroup获得某个群组所有在线用户信息(id 名字 头像等)
        Gateway::updateSession($client_id, $laychat_session);
        // 让当前客户端加入群组101，101是随意定义的一个组，这个组信息 需要在init.php中定义
        //Gateway::joinGroup($client_id, 101);

        $where['user_id'] = array('eq', $id);
        $group_list = M('GroupUser') -> where($where) -> getField('group_id', true);
        //dump($group_list);
        foreach ($group_list as $group) {
            Gateway::joinGroup($client_id, $group);
        }

        $_SESSION['laychat']['client_id'] = $client_id;

        $where_logout_time['id'] = array('eq', get_user_id());
        $logout_time = M('User') -> where($where_logout_time) -> getField('logout_time');

        if ($logout_time) {
            $where_message['to'] = array('eq', get_user_id());
            $where_message['timestamp'] = array('egt', $logout_time);
            $unread_message = M('Message') -> where($where_message) -> limit(0, 100) -> getField('data', true);
        }
        if (empty($unread_message)) {
            $unread_message = array();
        }

        // 通知所有客户端当前用户上线
        $online_message = array('message_type' => 'online', 'id' => $id);
        Gateway::sendToAll(json_encode($online_message));
        // 返回json数据
        die(json_encode(array('code' => 0, 'unread_message' => $unread_message, 'unread_notice_count' => $unread_notice_count ? '新消息' : 0)));
    }

    function init() {
        import("Home.ORG.Util.Gateway");
        Gateway::$registerAddress = '127.0.0.1:1238';
        $all_online_list = Gateway::getAllClientSessions();

        /**
         * 因为有些用户打开了多个tab页面，每个页面的socket链接都会有个session信息，
         * 那么某些用户也就是会有多个重复的session信息，这里做了去重
         * 同样，如果你的现有系统有好友列表数据可以直接复用，这部分可以去掉
         */
        $all_list = array();

        $field = 'id,name username,pic avatar,dept_id';
        $emp_list = model('User') -> getField($field);

        $dept_list = model('Dept') -> getField('id,id,name groupname', true);

        //dump($emp_list);
        foreach ($dept_list as &$dept) {
            foreach ($emp_list as $emp) {
                if (($emp['dept_id'] == $dept['id']) && ($emp['id'] !== get_user_id())) {
                    if (empty($emp['avatar'])) {
                        $emp['avatar'] = 'Public/layui/images/user.png';
                    }
                    $dept['list'][] = $emp;
                }
            }
        }

        foreach ($all_online_list as $info) {
            if (empty($info['id']) || $info['username'] === '未登录') {
                continue;
            }
            $info['status'] = 'online';
            $all_list[$info['id']] = $info;
        }

        M('User') -> where('id=' . get_user_id()) -> setField('im_status', 'online');
        // 自己的信息，这个session信息可以在你现有系统登录时设置，格式见login.php
        $mime_info = session('laychat');
        $mime_info['status'] = 'online';
        // 把自己从好友列表中删除
        unset($all_list[get_user_id()]);
        // 格式化登录者信息

        //$mime_info = json_encode($mime_info);
        //dump($mime_info);
        // 好友数量
        $count = count($all_online_list);
        // 好友列表数据
        $all_online_list = json_encode(array_values($all_list));

        $where_group_id['user_id'] = array('eq', get_user_id());
        $group_id_list = M('GroupUser') -> where($where_group_id) -> getField('group_id', true);

        if (!empty($group_id_list)) {
            $where_group['id'] = array('in', $group_id_list);
        } else {
            $where_group['_string'] = '1=2';
        }

        $group = M('Group') -> where($where_group) -> getField('id,id,name groupname');
        foreach ($group as &$val) {
            $val['avatar'] = 'Public/layui/images/group.png';
        }

        $return = new \stdClass();
        $return -> code = 0;
        $return -> msg = '';
        $return -> data -> mine = $mime_info;
        $return -> data -> friend = array_values($dept_list);
        $return -> data -> group = array_values($group);

        exit(json_encode($return));

    }

    function send_message($data = null, $is_json = false) {
        import("Home.ORG.Util.Gateway");
        Gateway::$registerAddress = '127.0.0.1:1238';

        //exit(json_encode($_REQUEST));
        // 聊天数据

        if ($is_json) {
            $data = json_decode($data, true);
        } else {
            $data = $_POST['data'];
        }

        // 发送者，也就是当前登录用户的id
        $from = $_SESSION['laychat']['id'];
        // 发送给谁
        $to = $data['to']['id'];
        // 类型，私聊(friend)还是群组(group)
        $type = $data['to']['type'];

        // 消息格式
        $message_data = array('username' => $_SESSION['laychat']['username'], 'avatar' => $_SESSION['laychat']['avatar'], 'id' => $type === 'friend' ? $from : $to, 'type' => $type, 'content' => htmlspecialchars($data['mine']['content']), 'timestamp' => time() * 1000, 'from_id' => $from, );

        $chat_message = array('message_type' => 'chatMessage', 'data' => $message_data);

        // 根据类型走不同的接口发送
        switch ($type) {
            // 私聊
            case 'friend' :
                Gateway::sendToUid($to, json_encode($chat_message));
                break;
            // 群聊
            case 'group' :
                Gateway::sendToGroup($to, json_encode($chat_message), $_SESSION['laychat']['client_id']);
                break;
        }

        $data['from'] = $from;
        $data['to'] = $to;
        $data['data'] = json_encode($message_data);
        $data['timestamp'] = time();
        $data['type'] = $type;

        $last_id = M('Message') -> add($data);
        // 记录消息到message表
        // 返回json
        $last_id = 1;
        //$code=$data;
        $code = $last_id ? 0 : 500;
        exit(json_encode(array('code' => $code)));
    }

    function members() {
        import("Home.ORG.Util.Gateway");
        Gateway::$registerAddress = '127.0.0.1:1238';
        // 获取群组当前所有在线用户信息
        $online_group_members = Gateway::getClientSessionsByGroup($_GET['id']);
        // 根据用户id去重
        $all_list = array();
        foreach ($online_group_members as $info) {
            $all_list[$info['id']] = $info;
        }
        $online_group_members = $all_list ? json_encode(array_values($all_list)) : '[]';

        $where['group_id'] = array('eq', request('id'));
        $member = M('GroupUser') -> where($where) -> getField('user_id', true);

        if ($member) {
            $where2['id'] = array('in', $member);
            $field = 'id,name username,pic avatar';
            $emp_list = M('User') -> where($where2) -> getField($field);
        } else {

        }
        $mime_info = session('laychat');
        $return = new \stdClass();
        $return -> code = 0;
        $return -> msg = '';
        $return -> data -> owner = $mime_info;
        $return -> data -> list = array_values($emp_list);
        exit(json_encode($return));
    }

    function upload() {
        $this -> _upload();
    }

    function chat_log() {
        // 对方的id，可能是uid，也可能是群组id
        $id = $_GET['?id'];
        // 起始消息id
        $hid = isset($_GET['hid']) ? (int)$_GET['hid'] : PHP_INT_MAX;
        // 消息类型，如果好友或者群组消息（两种消息共用message表）
        $type = isset($_GET['type']) ? $_GET['type'] : 'friend';
        // 查看类型，是上一页还是下一页

        // 用来存储历史消息数据
        $history = array();

        $model = M('Message');
        // 如果是查询好友历史消息(查询limit+1条，用来判断上一页或者下一页是否有数据，从而决定是否显示上一页 下一页)
        if ($type == 'friend') {
            $me = $_SESSION['laychat']['id'];
            $where['_string'] = ("((`to`=$me and `from`=$id)or(`to`=$id and `from`=$me)) and type='friend'");

            //$history_data = $db -> select('`data`,`hid`') -> from('message') ->
            //where(array('((`to` = :to_me AND `from` = :from_him) OR (`to` = :to_him AND `from` = :from_me))', "hid $operator $hid")) -> orderByAsc(array('hid'), $order_by_asc) -> bindValues(array('to_me' => $_SESSION['laychat']['id'], 'from_him' => $id, 'to_him' => $id, 'from_me' => $_SESSION['laychat']['id'])) -> limit($limit + 1) -> query();
            // 查询群组历史消息
        } else {
            $me = $_SESSION['laychat']['id'];
            $where['_string'] = ("`to`=$id and `type`='group'");
            //$history_data = $model -> where($where) -> field('data,id hid') -> select();
            //$history_data = $db -> select('`data`,`hid`') -> from('message') -> where("`to` = :group_id AND hid $operator $hid") -> orderByAsc(array('hid'), $order_by_asc) -> bindValue('group_id', $id) -> limit($limit + 1) -> query();
        }

        if (!empty($model)) {
            $history_data = $this -> _list($model, $where);
        }

        $this -> assign('history', $history_data);
        // 有历史消息的话
        if ($history_data) {
            // 如果是上一页，则需要反转下数组顺序
            if ($view_type === 'prev') {
                $history_data = array_reverse($history_data);
            }

            // reset将数组当前指针重置到第一条消息，找到本次消息数据中首尾消息id，用来方便下次上一页下一页查找
            reset($history_data);
            $first = current($history_data);
            // 格式化数据
            foreach ($history_data as $item) {
                $history[] = $item['data'];
            }
            $this -> assign('history', $history);
        }

        $this -> display();
    }

    function chat_list($from, $to) {
        // 对方的id，可能是uid，也可能是群组id
        $id = $_GET['?id'];
        // 起始消息id
        $hid = isset($_GET['hid']) ? (int)$_GET['hid'] : PHP_INT_MAX;
        // 消息类型，如果好友或者群组消息（两种消息共用message表）
        $type = isset($_GET['type']) ? $_GET['type'] : 'friend';
        // 查看类型，是上一页还是下一页

        // 用来存储历史消息数据
        $history = array();

        $model = M('Message');
        // 如果是查询好友历史消息(查询limit+1条，用来判断上一页或者下一页是否有数据，从而决定是否显示上一页 下一页)
        if ($type == 'friend') {
            $me = $from;
            $id = $to;
            $where['_string'] = ("((`to`=$me and `from`=$id)or(`to`=$id and `from`=$me)) and type='friend'");
        } else {
            $me = $_SESSION['laychat']['id'];
            $where['_string'] = ("`to`=$id and `type`='group'");
        }

        if (!empty($model)) {
            $history_data = $this -> _list($model, $where);
        }

        $this -> assign('history', $history_data);
        // 有历史消息的话
        if ($history_data) {
            // 如果是上一页，则需要反转下数组顺序
            if ($view_type === 'prev') {
                $history_data = array_reverse($history_data);
            }

            // reset将数组当前指针重置到第一条消息，找到本次消息数据中首尾消息id，用来方便下次上一页下一页查找
            reset($history_data);
            $first = current($history_data);
            // 格式化数据
            foreach ($history_data as $item) {
                $history[] = $item['data'];
            }
            $this -> assign('history', $history);
        }
        $this -> display();
    }

    function upload_img() {
        // 返回码，用来通知前端成功还是失败
        $code = 0;
        // 上传路径 文件名 错误信息(如果有的话)
        $upload_img_path = $msg = "";
        // 没找到文件
        if (empty($_FILES)) {
            $code = 400;
            $msg = "没找到文件";
        } else {
            // 如果是workerman运行的webserver，则使用$_FILES[0]['file_name']作为文件名，apache/php-fpm是用$_FILES['file']['name']。
            $file_name = PHP_SAPI === 'cli' ? $_FILES[0]['file_name'] : $_FILES['file']['name'];
            // 获得后缀名
            $extension_name = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
            // 计算上传路径
            $upload_img_path = C('CHAT_IMG_PATH') . bin2hex(pack('N', time()) . pack('n', rand(1, 65535))) . '.' . $extension_name;
            // 为了安全，禁止这些文件上传
            if ($extension_name === 'php' || $extension_name === 'asp' || $extension_name === 'jsp') {
                $code = 401;
                $msg = "上传文件非法";
            } else {
                // workerman的webserver上传
                if (PHP_SAPI === 'cli') {
                    if (!file_put_contents(__DIR__ . $upload_img_path, $_FILES[0]['file_data'])) {
                        $code = 500;
                        $msg = "保存文件失败";
                    }
                    // apache或者php-fpm
                } elseif (!move_uploaded_file($_FILES['file']['tmp_name'], $upload_img_path)) {
                    $code = 500;
                    $msg = "保存文件失败";
                }
            }
            // 检查是否是图片
            if ($code == 0 && !getimagesize($upload_img_path)) {
                $code = 502;
                $msg = "上传的文件不是图片";
                unlink($upload_img_path);
            }
        }
        // 判断是否是https协议
        $scheme = empty($_SERVER['HTTPS']) ? 'http://' : 'https://';
        // 获得url的path路径
        $url_path = substr($_SERVER['REQUEST_URI'], 0, strrpos($_SERVER['REQUEST_URI'], '/'));
        $url_path = $url_path ? $url_path : '';
        // 图片url路径
        $src = $scheme . $_SERVER['HTTP_HOST'] . $url_path . $upload_img_path;
        $return['code'] = $code;
        $return['msg'] = $msg;
        $return['data']['src'] = $src;
        exit(json_encode($return));
    }

    function upload_file() {

        // 返回码，用来通知前端成功还是失败
        $code = 0;
        // 上传路径 文件名 错误信息(如果有的话)
        $upload_img_path = $file_name = $msg = "";
        // 没找到文件
        if (empty($_FILES)) {
            $code = 400;
            $msg = "没找到文件";
        } else {
            // 如果是workerman运行的webserver，则使用$_FILES[0]['file_name']作为文件名，apache/php-fpm是用$_FILES['file']['name']。
            $file_name = PHP_SAPI === 'cli' ? $_FILES[0]['file_name'] : $_FILES['file']['name'];
            // 获得后缀名
            $extension_name = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
            // 计算上传路径
            $save_name = md5(mt_srand(time())) . bin2hex($file_name);
            $upload_img_path = C('CHAT_FILE_PATH') . $save_name;
            // 为了安全，禁止这些文件上传
            $forbidden_ext_names = array('php', 'php5', 'app', 'jsp', 'html', 'htm');
            // 检查文件后缀是否属于禁止上传的后缀
            if (in_array($extension_name, $forbidden_ext_names)) {
                $code = 401;
                $msg = "上传文件非法";
            } else {
                // workerman的webserver上传
                if (PHP_SAPI === 'cli') {
                    if (!file_put_contents(__DIR__ . $upload_img_path, $_FILES[0]['file_data'])) {
                        $code = 500;
                        $msg = "保存文件失败";
                    }
                    // apache或者php-fpm
                } elseif (!move_uploaded_file($_FILES['file']['tmp_name'], $upload_img_path)) {
                    $code = 500;
                    $msg = "保存文件失败";
                }
            }
        }
        // 判断是否是https协议
        $scheme = empty($_SERVER['HTTPS']) ? 'http://' : 'https://';
        // 获得url的path路径
        $url_path = substr($_SERVER['REQUEST_URI'], 0, strrpos($_SERVER['REQUEST_URI'], '/'));
        $url_path = $url_path ? $url_path : '';
        // 文件下载的url路径
        $src = $scheme . $_SERVER['HTTP_HOST'] . $url_path . $upload_img_path;
        $src = U('Chat/download', array('file_name' => $save_name));
        $return['code'] = $code;
        $return['msg'] = $msg;
        $return['data']['src'] = $src;
        $return['data']['name'] = $file_name;
        exit(json_encode($return));
    }

    function download($file_name) {
        $org_name = hex2bin(substr($file_name, 32));
        if (is_file(C('CHAT_FILE_PATH') . $file_name)) {
            /* 执行下载 */ //TODO: 大文件断点续传
            header("Content-Description: File Transfer");
            //header('Content-type: ' . $file['type']);
            //header('Content-Length:' . $file['size']);

            $ua = $_SERVER['HTTP_USER_AGENT'];
            if (preg_match('/MSIE/', $ua) || preg_match("/Trident\/7.0/", $ua)) {
                header('Content-Disposition: attachment; filename="' . rawurlencode($org_name) . '"');
            } else {
                header('Content-Disposition: attachment; filename="' . $org_name . '"');
            }
            readfile(C('CHAT_FILE_PATH') . $file_name);
            exit ;
        }
    }

}
